package com.jy.modules.cims.creditright.service;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.ibatis.exceptions.TooManyResultsException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.jy.modules.cims.common.exception.CimsException;
import com.jy.modules.cims.common.sysUtils.CollectionsUtils;
import com.jy.modules.cims.common.sysUtils.SearchParamUtil;
import com.jy.modules.cims.common.sysUtils.SimpleStringUtils;
import com.jy.modules.cims.component.sysAssist.BatchService;
import com.jy.modules.cims.data.common.dao.TCMmCreditPackageDao;
import com.jy.modules.cims.data.common.dto.TCMmCostPlanDTO;
import com.jy.modules.cims.data.common.dto.TCMmCreditDealDetailDTO;
import com.jy.modules.cims.data.common.dto.TCMmCreditPackageDTO;
import com.jy.modules.cims.data.dao.CostPlanDao;
import com.jy.modules.cims.data.dao.CreditRightDao;
import com.jy.modules.cims.data.dao.DealDao;
import com.jy.modules.cims.data.dto.CreditDetailDto;
import com.jy.modules.cims.data.dto.CreditDetailQueryDto;
import com.jy.modules.cims.data.dto.DealDto;
import com.jy.modules.cims.data.dto.credit.BatchCreditQueryDto;
import com.jy.modules.cims.data.dto.credit.BatchCreditQueryResultDto;
import com.jy.modules.cims.data.dto.credit.BatchCreditTranferListDTO;
import com.jy.modules.cims.data.dto.credit.CostPlanDto;
import com.jy.modules.cims.data.interact.core.credit.request.CreditForGetConstraint;
import com.jy.modules.cims.data.interact.core.credit.request.Request4036DTO;
import com.jy.modules.cims.interact.ICInteract;

/**
 * @description 通用债权基本服务层。
 * @author shengzhoutao
 * @date 2015-01-07 16:21:57
 */
@Service("com.jy.modules.cims.creditright.service.CreditRightService")
public class CreditRightService {
	private static final Logger logger = LoggerFactory.getLogger(CreditRightService.class);
	private static final int DEFAULT_BATCH_COUNT = 500;// 每一次执行的条数
	private static final String METHOD_INSERT_CREDIT_DEAL_DETAIL = "insertCreditDealDetailByBatch";// 批量插入债权交易明细处理方法名

	@Autowired
	private CreditRightDao creditRightDao;

	@Autowired
	public TCMmCreditPackageDao creditPackageDao;

	@Autowired
	public DealDao dealDao;

	@Autowired
	private CostPlanDao costPlanDao;

	@Autowired
	@Qualifier("com.jy.modules.cims.interact.CCInteractImpl")
	public ICInteract iCInteract;

	@Autowired
	@Qualifier("com.jy.modules.cims.component.sysAssist.BatchService")
	public BatchService batchService;

	/**
	 * @description 根据合作机构编号,债权包名称,合约编号，查询唯一一条债权包信息
	 * @author shengzhoutao
	 * @param cooperorgCode
	 *            合作机构编号
	 * @param creditPackageName
	 *            债权包名称
	 * @param contractCode
	 *            合约编号
	 * @return TCMmCreditPackageDTO 债权包信息对象
	 * @throws Exception
	 */
	public TCMmCreditPackageDTO getCreditPackageForUnique(final String cooperorgCode, final String creditPackageName, final String contractCode) {
		if (!SimpleStringUtils.hasText(cooperorgCode)) {
			logger.error("合作机构编号为空！");
			throw new CimsException("合作机构编号为空！");
		}

		if (!SimpleStringUtils.hasText(contractCode)) {
			logger.error("合约编号为空！");
			throw new CimsException("合约编号为空！");
		}

		if (!SimpleStringUtils.hasText(creditPackageName)) {
			logger.error("债权包名称为空！");
			throw new CimsException("债权包名称为空！");
		}

		TCMmCreditPackageDTO creditPackage = new TCMmCreditPackageDTO();
		creditPackage.setCooperorgCode(cooperorgCode);
		creditPackage.setCreditPackageName(creditPackageName);
		creditPackage.setContractCode(contractCode);

		TCMmCreditPackageDTO result = null;
		try {
			result = creditRightDao.findCreditPackage(SearchParamUtil.getSearchParam(creditPackage));
		} catch (Exception e) {
			if (e.getCause().getClass().getName().equals(TooManyResultsException.class.getName())) {
				throw new CimsException(MessageFormat.format("根据合作机构编号[{0}]、债权包名称[{1}]、合约编号[{2}]，查询债权包存在多条记录，不符合业务数据要求，请联系管理员！", new Object[] {
						cooperorgCode, creditPackageName, contractCode }));
			}
			throw new CimsException(MessageFormat.format("根据合作机构编号[{0}]、债权包名称[{1}]、合约编号[{2}]，查询债权包出现异常！", new Object[] { cooperorgCode,
					creditPackageName, contractCode }));
		}

		creditPackage = null;
		return result;
	}

	/**
	 * @description 批量插入债权交易明细
	 * @author shengzhoutao
	 * @param creditDealDetailList
	 */
	public void insertCreditDealDetail(List<TCMmCreditDealDetailDTO> creditDealDetailList) {

		batchService.batchInvoke(CreditRightService.class, METHOD_INSERT_CREDIT_DEAL_DETAIL, creditDealDetailList, null, DEFAULT_BATCH_COUNT);
	}

	public void insertCreditDealDetailByBatch(List<TCMmCreditDealDetailDTO> creditDealDetailList) {
		creditRightDao.insertCreditDealDetailByBatch(creditDealDetailList);
	}
	
	/**
	 * @description 批量修改债权明细状态
	 * @author shengzhoutao
	 * @param creditDetailList
	 *            要修改债权明细集合
	 * @param creditorStatus
	 *            要修改的债权明细状态
	 */
	public int updateCreditDetailStatus(final List<CreditDetailDto> creditDetailList, final String creditorStatus) {
		if (CollectionsUtils.isEmpty(creditDetailList)) {
			return 0;
		}

		int success = 0;
		int listSize = creditDetailList.size();
		List<Long> creditDetailIdList = new ArrayList<Long>();
		CreditDetailQueryDto creditDetail = null;

		for (int index = 0; index < listSize; index++) {
			CreditDetailDto detail = creditDetailList.get(index);
			creditDetailIdList.add(detail.getId());
			if ((index + 1) % DEFAULT_BATCH_COUNT == 0 || (index + 1) == listSize) {
				creditDetail = new CreditDetailQueryDto();
				creditDetail.setCreditDetailIdList(creditDetailIdList);
				creditDetail.setCreditorStatus(creditorStatus);
				success += creditRightDao.updateCreditDetailStatusByCreditorDetailIdList(SearchParamUtil.getSearchParam(creditDetail));
				creditDetailIdList.clear();
			}
		}
		creditDetailIdList = null;
		return success;
	}

	/**
	 * @description 批量修改债权明细状态
	 * @author shengzhoutao
	 * @param creditDetailList
	 *            要修改债权明细集合
	 * @param creditorStatus
	 *            要修改的债权明细状态
	 */
	public int updateCreditDetailStatusByTransferIdList(final List<CreditDetailDto> creditDetailList, final String creditorStatus) {
		if (CollectionsUtils.isEmpty(creditDetailList)) {
			return 0;
		}

		int success = 0;
		int listSize = creditDetailList.size();
		List<String> transferIdList = new ArrayList<String>();
		CreditDetailQueryDto creditDetail = null;
		for (int index = 0; index < listSize; index++) {
			CreditDetailDto detail = creditDetailList.get(index);
			transferIdList.add(detail.getTransferId());
			if ((index + 1) % DEFAULT_BATCH_COUNT == 0 || (index + 1) == listSize) {
				creditDetail = new CreditDetailQueryDto();
				creditDetail.setTransferIdList(transferIdList);
				creditDetail.setCreditorStatus(creditorStatus);
				success += creditRightDao.updateCreditDetailStatusByTransferIdList(SearchParamUtil.getSearchParam(creditDetail));
				transferIdList.clear();
			}
		}

		transferIdList = null;
		return success;
	}

	/**
	 * @description 修改债权明细状态，债权已结算：条件是该债权所有的期数的结算计划已经结算完成;
	 *              或者是异常结算(11-债权转让异常结算;13-贷款转出异常结算;16-债权受让异常结算)提前结清，合约还款计划变更类型类型:2-提前结清，违约处理方式:01-提前结清.
	 * @param creditDetail
	 * @param creditDetailList
	 * @return
	 */
	public int updateCreditDetailStatusForSettle(final CreditDetailQueryDto creditDetail, final List<CreditDetailDto> creditDetailList) {
		if (CollectionsUtils.isEmpty(creditDetailList) || null == creditDetail) {
			return 0;
		}

		int success = 0;
		int listSize = creditDetailList.size();
		List<String> transferIdList = new ArrayList<String>();
		CreditDetailQueryDto newCreditDetail = null;
		for (int index = 0; index < listSize; index++) {
			CreditDetailDto detail = creditDetailList.get(index);
			transferIdList.add(detail.getTransferId());
			if ((index + 1) % DEFAULT_BATCH_COUNT == 0 || (index + 1) == listSize) {
				newCreditDetail = creditDetail;
				newCreditDetail.setTransferIdList(transferIdList);
				success += creditRightDao.updateCreditDetailStatusForSettle(SearchParamUtil.getSearchParam(newCreditDetail));
				transferIdList.clear();
			}
		}

		transferIdList = null;
		return success;
	}
	
	/**
	 * @description 根据债权编号、债权转让编号、当前还款期次，修改结算计划表的结算状态
	 * @author shengzhoutao
	 * @param creditorCode
	 *            债权编号
	 * @param transferId
	 *            债权转让编号
	 * @param currentTime
	 *            当前期次
	 * @param planStatus
	 *            结算状态
	 * @return
	 */
	public int updateCostPlanStatusByCredit(final String creditorCode, final String transferId, final long currentTime, String costStatus) {
		TCMmCostPlanDTO dto = new TCMmCostPlanDTO();
		dto.setCreditorCode(creditorCode);
		dto.setTransferId(transferId);
		dto.setCurrentTime(currentTime);
		dto.setPlanStatus(costStatus);

		return costPlanDao.updateCostPlanStatusByCredit(SearchParamUtil.getSearchParam(dto));
	}

	/**
	 * @description 修改债权明细的剩余还款期数(等于该债权的结算计划的剩余未结算的总期数)
	 * @author shengzhoutao
	 * @param creditDetailQueryDto
	 * @return
	 */
	public int updateCreditDetailResidueRepayPeriodForSettle(CreditDetailQueryDto creditDetailQueryDto) {

		// 修改债权明细的剩余还款期数减一，关联结算计划，剩余未结算的期数。
		return creditRightDao.updateCreditDetailResidueRepayPeriodForSettle(SearchParamUtil.getSearchParam(creditDetailQueryDto));
	}

	/**
	 * @description 根据债权编号、债权转让编号、当前还款期次，修改结算计划表的结算状态
	 * @author shengzhoutao
	 * @param creditDetailQueryDto
	 * @return
	 */
	public int updateCostPlanStatusForSettle(CreditDetailQueryDto creditDetailQueryDto) {

		return costPlanDao.updateCostPlanStatusForSettle(SearchParamUtil.getSearchParam(creditDetailQueryDto));
	}
	
	/**
	 * 
	 * @Description 根据债权明细月还，修改债权结算计划的月还
	 * @author zhangmi
	 * @date 2016-3-31
	 */
	public void updateThisRepaySumSql(CostPlanDto costPlanDto) throws Exception{
		costPlanDao.updateThisRepaySumSql(SearchParamUtil.getSearchParam(costPlanDto));
	}
	/**
	 * @description 统计结算计划：按照输入条件统计应该结算的结算计划
	 * @author shengzhoutao
	 * @param creditDetailQueryDto
	 * @return
	 */
	public TCMmCostPlanDTO statCostPlanForSettle(CreditDetailQueryDto creditDetailQueryDto) {

		return costPlanDao.statCostPlanForSettle(SearchParamUtil.getSearchParam(creditDetailQueryDto));
	}

	/**
	 * @description 查询债权
	 * @author shengzhoutao
	 * @param creditDetailQueryDto
	 *            查询债权对象
	 * @return List<CreditDetailDto>
	 */
	public List<CreditDetailDto> getCreditDetailByUnequalCoreCreditStatus(CreditDetailQueryDto creditDetailQueryDto) {
		return creditRightDao.getCreditDetailByUnequalCoreCreditStatus(SearchParamUtil.getSearchParam(creditDetailQueryDto));

	}

	/**
	 * @description 根据流水号取消发送给核心系统的受让的债权
	 * @author shengzhoutao
	 * @date 2015-07-21
	 * @param dealCode
	 *            交易流水号
	 */
	public List<CreditDetailDto> getCreditDetailByDealCode(final String dealCode) {
		// 根据交易流水号查询债权明细
		DealDto dealDto = new DealDto();
		dealDto.setDealCode(dealCode);
		return dealDao.getDealDetailByCreditList(SearchParamUtil.getSearchParam(dealDto));
	}
	
	/**
	 * @description 受让赎回根据流水号取消发送给核心系统的受让的债权
	 * @param dealCode
	 *            交易流水号
	 */
	public List<CreditDetailDto> getCreditListByTransfereeRedemp(final String dealCode) {
		// 根据交易流水号查询债权明细
		DealDto dealDto = new DealDto();
		dealDto.setDealCode(dealCode);
		return dealDao.getCreditListByTransfereeRedemp(SearchParamUtil.getSearchParam(dealDto));
	}

	/**
	 * @description 调用核心系统撤销受让的债权
	 * @author shengzhoutao
	 * @date 2015-07-21
	 * @param dealCode
	 *            交易流水号
	 */
	public void cancelSRCreditsToCoreByDealCode(final String dealCode) {
		// 根据交易流水号查询债权明细
		List<CreditDetailDto> creditDetailList = getCreditDetailByDealCode(dealCode);
		if (CollectionsUtils.isEmpty(creditDetailList)) {
			return;
		}

		// 调用撤销接口
		Request4036DTO request = new Request4036DTO();
		List<CreditForGetConstraint> creditList = tranCreditForGetConstraint(dealCode, creditDetailList);
		request.setCreditList(creditList);
		iCInteract.cancelSRCreditsToCore(request);

		creditList = null;
		request = null;
	}

	/**
	 * @description 判断是否生成全部结算计划
	 * @author shengzhoutao
	 * @date 2015-07-21
	 * @param dealCode
	 *            交易流水号
	 * @return true:全部生成; false:没有全部生成
	 */
	public boolean isFullCreatCostPlan(final String dealCode) {
		DealDto dealDto = new DealDto();
		dealDto.setDealCode(dealCode);
		Long count1 = creditRightDao.getDistinctTransferIdCountForCostPlan(SearchParamUtil.getSearchParam(dealDto));
		Long count2 = creditRightDao.getDistinctTransferIdCountForCreditDetail(SearchParamUtil.getSearchParam(dealDto));

		dealDto = null;
		if (count1.intValue() == count2.intValue()) {
			return true;
		}

		return false;
	}

	/**
	 * 
	 * @param creditRightList
	 * @return
	 */
	public List<CreditDetailDto> getUpdateCreditDetail(List<CreditDetailDto> creditRightList){
		BatchCreditQueryDto batchCreditQueryDto = new BatchCreditQueryDto();
		List<BatchCreditTranferListDTO> queryList = new ArrayList<BatchCreditTranferListDTO>();
		for (CreditDetailDto dto : creditRightList) {
			BatchCreditTranferListDTO queryDto = new BatchCreditTranferListDTO();
			queryDto.setTransferId(dto.getTransferId());
			queryDto.setType(dto.getCreditSource());
			queryList.add(queryDto);
		}
		
		batchCreditQueryDto.setList(queryList);
		BatchCreditQueryResultDto batchCreditQueryResultDto = iCInteract.getCreditDetail(batchCreditQueryDto);
		if (null == batchCreditQueryResultDto) {
			return null;
		}
		
		List<CreditDetailDto> updateList = new ArrayList<CreditDetailDto>();
		List<CreditDetailDto> transferList = batchCreditQueryResultDto.getTransferList();
		if (CollectionsUtils.isNotEmpty(transferList)) {
			updateList = CollectionsUtils.union(updateList, transferList);
		}

		List<CreditDetailDto> creditList = batchCreditQueryResultDto.getCreditList();
		if (CollectionsUtils.isNotEmpty(creditList)) {
			updateList = CollectionsUtils.union(updateList, creditList);
		}
		
		return updateList;
		//creditRightDao.updateCreditDetailAdcanceFinishDate(updateList);
	}
	
	/**
	 * 
	 * @param dealCode
	 * @param creditDetailList
	 * @return
	 */
	private List<CreditForGetConstraint> tranCreditForGetConstraint(final String dealCode, final List<CreditDetailDto> creditDetailList) {
		List<CreditForGetConstraint> creditList = new ArrayList<CreditForGetConstraint>();
		CreditForGetConstraint creditForGetConstraint = null;
		for (CreditDetailDto creditDetailDto : creditDetailList) {
			creditForGetConstraint = new CreditForGetConstraint();
			creditForGetConstraint.setBatchId(dealCode);// 批次号
			creditForGetConstraint.setContractNo(creditDetailDto.getContractCode());// 合同编号
			creditForGetConstraint.setOtherCreditId(creditDetailDto.getCreditCode());// 债权编号
			creditList.add(creditForGetConstraint);
		}
		creditForGetConstraint = null;
		return creditList;
	}
}